package com.zsd.android.webrtcdemo.socket;

import android.app.Activity;
import android.content.Intent;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.zsd.android.webrtcdemo.ChatRoomActivity;
import com.zsd.android.webrtcdemo.connection.PeerConnectionManager;

import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import org.webrtc.EglBase;
import org.webrtc.IceCandidate;
import org.webrtc.SessionDescription;

import java.net.URI;
import java.net.URISyntaxException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

public class JavaWebSocket {

    private PeerConnectionManager peerConnectionManager;
    private WebSocketClient socketClient;
    private Activity activity;

    public JavaWebSocket(Activity activity) {
        this.activity = activity;
    }

    public void connect(String wss) {
        peerConnectionManager = PeerConnectionManager.getInstance();
        try {
            URI uri = new URI(wss);
            socketClient = new WebSocketClient(uri) {
                @Override
                public void onOpen(ServerHandshake handshakedata) {
                    activity.startActivity(new Intent(activity, ChatRoomActivity.class));
                }

                @Override
                public void onMessage(String message) {
                    handleMessage(message);
                }

                @Override
                public void onClose(int code, String reason, boolean remote) {

                }

                @Override
                public void onError(Exception ex) {

                }
            };
            if (wss.startsWith("wss")) {
                try {
                    SSLContext sslContext = SSLContext.getInstance("TLS");
                    sslContext.init(null, new TrustManager[]{new IgnoreTrustManager()}, new SecureRandom());
                    SSLSocketFactory factory = null;
                    if (sslContext != null) {
                        factory = sslContext.getSocketFactory();
                    }
                    if (factory != null) {
                        socketClient.setSocketFactory(factory);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            socketClient.connect();
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
    }

    private void handleMessage(String message) {
        Map map = JSON.parseObject(message, Map.class);
        String eventName = (String) map.get("eventName");
        if ("_peers".equals(eventName)) {
            //p2p通信
            handleJoinRoom(map);
        } else if ("_ice_candidate".equals(eventName)) {
            //本机发送offer的时候对方响应，返回_ice_candidate，调用多次
            handleRemoteCandidate(map);
        } else if ("_answer".equals(eventName)) {
            //对方的SDP
            handleAnswer(map);
        }
    }

    private void handleJoinRoom(Map map) {
        Map data = (Map) map.get("data");
        JSONArray arr;
        if (data != null) {
            arr = (JSONArray) data.get("connections");
            String json = JSONObject.toJSONString(arr, SerializerFeature.WriteClassName);
            ArrayList<String> connections = (ArrayList<String>) JSONObject.parseArray(json, String.class);
            String mId = (String) data.get("you");
            peerConnectionManager.joinRoom(this, connections, mId, true);
        }
    }

    private void handleRemoteCandidate(Map map) {
        Map data = (Map) map.get("data");
        String socketId;
        if (data != null) {
            socketId = (String) data.get("socketId");
            String sdpMid = (String) data.get("id");
            sdpMid = (null == sdpMid) ? "video" : sdpMid;
            int sdpMLineIndex = (int) Double.parseDouble(String.valueOf(data.get("label")));
            String candidate = (String) data.get("candidate");

            IceCandidate iceCandidate = new IceCandidate(sdpMid, sdpMLineIndex, candidate);
            peerConnectionManager.onRemoteIceCandidate(socketId, iceCandidate);
        }
    }

    private void handleAnswer(Map map) {
        Map data = (Map) map.get("data");
        Map sdpDic = null;
        if (data != null) {
            sdpDic = (Map) data.get("sdp");
            String socketId = (String) data.get("socketId");
            String sdp = (String) sdpDic.get("sdp");
            peerConnectionManager.onReceiverAnswer(socketId, sdp);
        }
    }

    /**
     * 事件类型：
     * __join
     * __answer
     * __offer
     * __ice_candidate
     * __peer
     * @param roomId
     */
    public void joinRoom(String roomId) {
        HashMap<String, Object> map = new HashMap<>();
        map.put("eventName", "__join");
        HashMap<String, String> childMap = new HashMap<>();
        childMap.put("room", roomId);
        map.put("data", childMap);
        JSONObject jsonObject = new JSONObject(map);
        String jsonStr = jsonObject.toJSONString();
        socketClient.send(jsonStr);
    }

    public void sendOffer(String socketId, SessionDescription localDescription) {
        HashMap<String, Object> childMap1 = new HashMap<>();
        childMap1.put("type", "offer");
        childMap1.put("sdp", localDescription.description);

        HashMap<String, Object> childMap2 = new HashMap<>();
        childMap2.put("socketId", socketId);
        childMap2.put("sdp", childMap1);

        HashMap<String, Object> map = new HashMap<>();
        map.put("eventName", "__offer");
        map.put("data", childMap2);

        JSONObject jsonObject = new JSONObject(map);
        String jsonStr = jsonObject.toString();
        socketClient.send(jsonStr);
    }

    public void sendIceCandidate(String socketId, IceCandidate iceCandidate) {
        HashMap<String, Object> childMap = new HashMap<>();
        childMap.put("id", iceCandidate.sdpMid);
        childMap.put("label", iceCandidate.sdpMLineIndex);
        childMap.put("candidate", iceCandidate.sdp);
        childMap.put("socketId", socketId);

        HashMap<String, Object> map = new HashMap<>();
        map.put("eventName", "__ice_candidate");
        map.put("data", childMap);

        JSONObject jsonObject = new JSONObject(map);
        String jsonStr = jsonObject.toString();
        socketClient.send(jsonStr);
    }

    public boolean isOpen() {
        if (socketClient == null) {
            return false;
        }
        return socketClient.isOpen();
    }

    public boolean isClosed() {
        if (socketClient == null) {
            return true;
        }
        return socketClient.isClosed();
    }

    /**
     * 忽略证书
     */
    public static class IgnoreTrustManager implements X509TrustManager {
        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {

        }

        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {

        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[0];
        }
    }
}
